/*
 * Copyright (c) 1995, 2010, Oracle and/or its affiliates. All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions
 * are met:
 *
 *   - Redistributions of source code must retain the above copyright
 *     notice, this list of conditions and the following disclaimer.
 *
 *   - Redistributions in binary form must reproduce the above copyright
 *     notice, this list of conditions and the following disclaimer in the
 *     documentation and/or other materials provided with the distribution.
 *
 *   - Neither the name of Oracle or the names of its
 *     contributors may be used to endorse or promote products derived
 *     from this software without specific prior written permission.
 *
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS
 * IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
 * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
 * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE COPYRIGHT OWNER OR
 * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
 * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
 * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
 * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 */

package com.oracle.tutorial.jdbc;

import java.sql.CallableStatement;
import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.sql.Statement;

import java.util.HashMap;

public class StoredProcedureJavaDBSample {

  private String dbName;
  private Connection con;
  private String dbms;


  public StoredProcedureJavaDBSample(Connection connArg, String dbName,
                                     String dbmsArg) {
    super();
    this.con = connArg;
    this.dbName = dbName;
    this.dbms = dbmsArg;
  }

  public static void showSuppliers(ResultSet[] rs) throws SQLException {
    Connection con = DriverManager.getConnection("jdbc:default:connection");
    Statement stmt = null;

    String query =
      "select SUPPLIERS.SUP_NAME, COFFEES.COF_NAME " + "from SUPPLIERS, COFFEES " +
      "where SUPPLIERS.SUP_ID = COFFEES.SUP_ID " + "order by SUP_NAME";

    stmt = con.createStatement();
    rs[0] = stmt.executeQuery(query);

  }

  public void createProcedure(Connection con,
                              String jarPathName) throws SQLException {

    Statement stmt = null;
    Statement stmtDrop = null;
    CallableStatement cs2 = null;
    CallableStatement cs2a = null;
    CallableStatement cs3 = null;

    String queryDrop = "DROP PROCEDURE SHOW_SUPPLIERS";
    String query =
      "CREATE PROCEDURE SHOW_SUPPLIERS() " + "PARAMETER STYLE JAVA " +
      "LANGUAGE JAVA " + "DYNAMIC RESULT SETS 1 " +
      "EXTERNAL NAME 'com.oracle.tutorial.jdbc.StoredProcedureJavaDBSample.showSuppliers'";

    String query2 =
      "CALL sqlj.install_jar('" + jarPathName + "','" + dbName + ".JDBCTutorial',0)";
    String query2a =
      "CALL sqlj.replace_jar('" + jarPathName + "','" + dbName + ".JDBCTutorial')";
    String query3 =
      "CALL syscs_util.syscs_set_database_property('derby.database.classpath','" +
      dbName + ".JDBCTutorial')";

    try {
      System.out.println("Calling DROP PROCEDURE");
      stmtDrop = con.createStatement();
      stmtDrop.execute(queryDrop);
    } catch (SQLException e) {
      JDBCTutorialUtilities.printSQLException(e);
    } finally {
      stmtDrop.close();
    }
    try {
      System.out.println("Calling CREATE PROCEDURE");
      stmt = con.createStatement();
      stmt.execute(query);
    } catch (SQLException e) {
      JDBCTutorialUtilities.printSQLException(e);
    } finally {
      stmt.close();
    }
    try {
      System.out.println("Calling " + query2);
      cs2 = con.prepareCall(query2);
      cs2.execute();
    } catch (SQLException e2) {
      JDBCTutorialUtilities.printSQLException(e2);
    } finally {
      cs2.close();
      try {
        System.out.println("Calling " + query2a);
        cs2a = con.prepareCall(query2a);
        cs2a.execute();
      } catch (SQLException e2a) {
        JDBCTutorialUtilities.printSQLException(e2a);
      } finally {
        cs2a.close();
      }
    }
    try {
      System.out.println("Calling " + query3);
      cs3 = con.prepareCall(query3);
      cs3.execute();
    } catch (SQLException e) {
      JDBCTutorialUtilities.printSQLException(e);
    } finally {
      cs3.close();
    }
  }

  public void runStoredProcedure(Connection con) throws SQLException {
    CallableStatement cs = null;

    try {
      cs = con.prepareCall("{call SHOW_SUPPLIERS()}");
      cs.execute();
      ResultSet rs = cs.getResultSet();
      while (rs.next()) {
        String supplier = rs.getString("SUP_NAME");
        String coffee = rs.getString("COF_NAME");
        System.out.println(supplier + ": " + coffee);
      }
    } catch (SQLException e) {
      JDBCTutorialUtilities.printSQLException(e);
    } finally {
      cs.close();
    }
  }

  public static void main(String[] args) {

    JDBCTutorialUtilities myJDBCTutorialUtilities;
    Connection myConnection = null;
    if (args[0] == null) {
      System.err.println("Properties file not specified at command line");
      return;
    } else {
      try {
        myJDBCTutorialUtilities = new JDBCTutorialUtilities(args[0]);
      } catch (Exception e) {
        System.err.println("Problem reading properties file " + args[0]);
        e.printStackTrace();
        return;
      }
    }
    try {
      myConnection = myJDBCTutorialUtilities.getConnection();
      StoredProcedureJavaDBSample mySP =
        new StoredProcedureJavaDBSample(myConnection,
                                        myJDBCTutorialUtilities.dbName,
                                        myJDBCTutorialUtilities.dbms);
      
      JDBCTutorialUtilities.initializeTables(myConnection,
                                             myJDBCTutorialUtilities.dbName,
                                             myJDBCTutorialUtilities.dbms);

      System.out.println("\nCreating stored procedure:");
      mySP.createProcedure(myConnection, myJDBCTutorialUtilities.jarFile);

      System.out.println("\nRunning stored procedure:");
      mySP.runStoredProcedure(myConnection);


    } catch (SQLException e) {
      JDBCTutorialUtilities.printSQLException(e);
    } finally {
      JDBCTutorialUtilities.closeConnection(myConnection);
    }

  }
}
